package org.zongf.learn.grpc.starter.core;

import io.grpc.stub.AbstractStub;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.zongf.learn.grpc.starter.anno.EnableGrpcClient;
import org.zongf.learn.grpc.starter.anno.GrpcClient;
import org.zongf.learn.grpc.starter.base.EnableBaseBeanDefinitionRegistrar;
import org.zongf.learn.grpc.starter.config.GrpcClientConfig;
import org.zongf.learn.grpc.starter.util.ClassUtil;

/** @EnableXXX 组件扫描器, @EnableXXX 注解需要有: String[] basePackages() 属性
 * @author zongf
 * @since 2020-11-26
 */
@Slf4j
public class GrpcClientRegister extends EnableBaseBeanDefinitionRegistrar implements ApplicationContextAware {

    public GrpcClientRegister() {
        super(EnableGrpcClient.class, GrpcClient.class, GrpcClientFactoryBean.class);
    }

    @Override
    protected void doRegisterBeanDefinition(BeanDefinitionRegistry registry, BeanDefinition beanDefinition) {

        Class beanClass = ClassUtil.forName(beanDefinition.getBeanClassName(), registry.getClass().getClassLoader());

        GrpcClient annotation = (GrpcClient) beanClass.getAnnotation(GrpcClient.class);

        Class<? extends AbstractStub> grpcStubClass = annotation.stub();

        String serviceName = annotation.service();


        BeanDefinition genericBeanDefinition = BeanDefinitionBuilder
                .genericBeanDefinition(this.beanFactoryClass)
                .setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE)
                .addPropertyValue("grpcStubClass", grpcStubClass)
                .addPropertyValue("serviceName", serviceName)
                .addPropertyValue("type", grpcStubClass)
                .addPropertyValue("applicationContext", applicationContext)
                .getBeanDefinition();


        // 向spring 容器注册bean
        registry.registerBeanDefinition(grpcStubClass.getCanonicalName(), genericBeanDefinition);

    }

    private ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
